package com.ks.core.util;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * <p>Http工具类
 * <p>
 * <p>Http工具类，为系统提供通用Http访问操作方法：
 * <p>
 * <p>1、发送GET请求；
 * <p>2、发送POST请求。
 */
@Slf4j
public class HttpUtil {
    private static final CloseableHttpClient httpclient = HttpClients.createDefault();

    /**
     * 针对微信发送请求，前置需要使用证书,如果不需要使用证书请不要使用这个接口
     * @param
     * @param data<XML格式
     * @param  mchId 证书密码默认为您的商户ID（如：10010000）
     * @return
     */
    public static String doPostByWXSSL(String url, String data, InputStream inputStream, String mchId) {
        StringBuffer message = new StringBuffer();
        try {
            KeyStore keyStore  = KeyStore.getInstance("PKCS12");
            keyStore.load(inputStream, mchId.toCharArray());
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, mchId.toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1" },
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();
            HttpPost httpost = new HttpPost(url);

            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            System.out.println("executing request" + httpost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                System.out.println("--------------------发送微信接收参数开始--------------------");
                System.out.println("请求响应状态：" + response.getStatusLine());
                if (entity != null) {
                    System.out.println("响应字节总长度: " + entity.getContentLength());
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
                    String text;
                    while ((text = bufferedReader.readLine()) != null) {
                        message.append(text);
                    }
                }
                System.out.println("--------------------发送微信接收参数结束--------------------");
                EntityUtils.consume(entity);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                response.close();
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return message.toString();

    }


    /**
     * 发送HttpGet请求
     *
     * @param url
     * @return
     */
    public static String sendGet(String url) {

        HttpGet httpget = new HttpGet(url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        String result = null;
        try {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }



    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * <p>发送GET请求
     *
     * @param url GET请求地址
     * @return 与当前请求对应的响应内容字节数组
     */
    public static byte[] doGet(String url) {

        return HttpUtil.doGet(url, null, null, 0);
    }

    /**
     * <p>发送GET请求
     *
     * @param url       GET请求地址
     * @param headerMap GET请求头参数容器
     * @return 与当前请求对应的响应内容字节数组
     */
    public static byte[] doGet(String url, Map headerMap) {

        return HttpUtil.doGet(url, headerMap, null, 0);
    }

    /**
     * <p>发送GET请求
     *
     * @param url       GET请求地址
     * @param proxyUrl  代理服务器地址
     * @param proxyPort 代理服务器端口号
     * @return 与当前请求对应的响应内容字节数组
     * @modify 窦海宁, 2012-03-19
     */
    public static byte[] doGet(String url, String proxyUrl, int proxyPort) {

        return HttpUtil.doGet(url, null, proxyUrl, proxyPort);
    }

    /**
     * <p>发送GET请求
     *
     * @param url       GET请求地址
     * @param headerMap GET请求头参数容器
     * @param proxyUrl  代理服务器地址
     * @param proxyPort 代理服务器端口号
     * @return 与当前请求对应的响应内容字节数组
     * @modify 窦海宁, 2012-03-19
     */
    public static byte[] doGet(String url, Map headerMap, String proxyUrl, int proxyPort) {

        byte[] content = null;
        HttpClient httpClient = new HttpClient();
        GetMethod getMethod = new GetMethod(url);

        if (headerMap != null) {

            //头部请求信息
            if (headerMap != null) {

                Iterator iterator = headerMap.entrySet().iterator();
                while (iterator.hasNext()) {

                    Entry entry = (Entry) iterator.next();
                    getMethod.addRequestHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
        }

        if (StringUtils.isNotBlank(proxyUrl)) {

            httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
        }

        //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 10000);
        //postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER , new DefaultHttpMethodRetryHandler());
        InputStream inputStream = null;
        try {

            if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

                //读取内容
                inputStream = getMethod.getResponseBodyAsStream();
                content = IOUtils.toByteArray(inputStream);
            } else {

                System.err.println("Method failed: " + getMethod.getStatusLine());
            }
        } catch (IOException ex) {

            ex.printStackTrace();
        } finally {

            IOUtils.closeQuietly(inputStream);
            getMethod.releaseConnection();
        }
        return content;
    }

    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param parameterMap POST请求参数容器
     * @return 与当前请求对应的响应内容字节数组
     */
    public static byte[] doPost(String url, Map parameterMap) {
        return HttpUtil.doPost(url, null, parameterMap, "UTF-8", null, 0);
    }

    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param parameterMap POST请求参数容器
     * @param paramCharset 参数字符集名称
     * @return 与当前请求对应的响应内容字节数组
     * @modify 窦海宁, 2012-05-21
     */
    public static byte[] doPost(String url, Map parameterMap, String paramCharset) {

        return HttpUtil.doPost(url, null, parameterMap, paramCharset, null, 0);
    }

    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param headerMap    POST请求头参数容器
     * @param parameterMap POST请求参数容器
     * @param paramCharset 参数字符集名称
     * @return 与当前请求对应的响应内容字节数组
     * @modify 窦海宁, 2012-05-21
     */
    public static byte[] doPost(String url, Map headerMap, Map parameterMap, String paramCharset) {

        return HttpUtil.doPost(url, headerMap, parameterMap, paramCharset, null, 0);
    }


    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param parameterMap POST请求参数容器
     * @param paramCharset 参数字符集名称
     * @param proxyUrl     代理服务器地址
     * @param proxyPort    代理服务器端口号
     * @return 与当前请求对应的响应内容字节数组
     */
    public static byte[] doPost(String url, Map parameterMap, String paramCharset, String proxyUrl, int proxyPort) {

        return HttpUtil.doPost(url, null, parameterMap, paramCharset, proxyUrl, proxyPort);
    }

    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param headerMap    POST请求头参数容器
     * @param parameterMap POST请求参数容器
     * @param paramCharset 参数字符集名称
     * @param proxyUrl     代理服务器地址
     * @param proxyPort    代理服务器端口号
     * @return 与当前请求对应的响应内容字节数组
     * @modify 窦海宁, 2012-05-21
     */
    public static byte[] doPost(String url, Map headerMap, Map parameterMap, String paramCharset, String proxyUrl, int proxyPort) {

        byte[] content = null;
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod(url);

        if (StringUtils.isNotBlank(paramCharset)) {

            postMethod.getParams().setContentCharset(paramCharset);
            postMethod.getParams().setHttpElementCharset(paramCharset);
        }

        if (headerMap != null) {

            //头部请求信息
            if (headerMap != null) {

                Iterator iterator = headerMap.entrySet().iterator();
                while (iterator.hasNext()) {

                    Entry entry = (Entry) iterator.next();
                    postMethod.addRequestHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
        }

        Iterator iterator = parameterMap.keySet().iterator();
        while (iterator.hasNext()) {

            String key = (String) iterator.next();
            Object value = parameterMap.get(key);
            if (ToolUtil.isNotEmpty(value)) {
                postMethod.addParameter(key, String.valueOf(value));
            }
        }

        if (StringUtils.isNotBlank(proxyUrl)) {

            httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
        }

        //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 10000);
        //postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER , new DefaultHttpMethodRetryHandler());
        InputStream inputStream = null;
        try {

            if (httpClient.executeMethod(postMethod) == HttpStatus.SC_OK) {

                //读取内容
                inputStream = postMethod.getResponseBodyAsStream();
                content = IOUtils.toByteArray(inputStream);
            } else {

                System.err.println("Method failed: " + postMethod.getStatusLine());
            }
        } catch (IOException ex) {

            ex.printStackTrace();
        } finally {

            IOUtils.closeQuietly(inputStream);
            postMethod.releaseConnection();
        }
        return content;
    }


    public static void main(String[] args) {
        String random = "221321";
        String str = "repair*api*md5";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateNowStr = sdf.format(new Date());
        String token=string2MD5(str+random+dateNowStr);
        System.out.println(token);
        String url = "https://esbtest.yuhong.com.cn/api_repair/ZPS_SAPTOOA_ZPROJ01";
        Map<String,Object> json =new HashMap<>();
        json.put("IV_BUKRS", "");
        json.put("IV_PSPNR", "");
        json.put("IV_POST1", "");
        json.put("IV_ZPM_PERNR", "114708");
        json.put("IV_ZSO_PERNR", "");
        json.put("IV_ZCR_PERNR", "");
        HttpPost httpost =new HttpPost(url);
        httpost.addHeader("Content-Type", "application/json");
        httpost.addHeader("random", random);
        httpost.addHeader("token", token);
        System.out.println("executing request" + httpost.getRequestLine());
        httpost.setEntity(new StringEntity(json.toString(), "UTF-8"));
        try {
            CloseableHttpResponse response = httpclient.execute(httpost);
            System.out.println(response);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public static String string2MD5(String inStr) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
            return "";
        }
        char[] charArray = inStr.toCharArray();
        byte[] byteArray = new byte[charArray.length];
        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16)
                hexValue.append("0");
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString().toUpperCase();
    }

    public static String doPostWbsHttpClient(String url, String data, String token,String random) throws ConnectException {
        try {
            DefaultHttpClient httpClient = null;
            if (url.toLowerCase().startsWith("https://")) {
                System.out.println("use ssl");
                httpClient = new SSLClient();
            } else {
                System.out.println("use nonssl");
                httpClient = new DefaultHttpClient();
            }

            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json");
            httpPost.addHeader("random", random);
            httpPost.addHeader("token", token);

            StringEntity se = new StringEntity(data, "UTF-8");
            se.setContentType("application/json");
            se.setContentEncoding(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
            httpPost.setEntity(se);
            HttpResponse response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new ConnectException("连接银企服务器发生错误！");
            }
            String body = EntityUtils.toString(response.getEntity());
            System.out.println(body);
            return body;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(" ===== doPostByHttpClient() ERROR ===== ");
            throw new ConnectException(e.getMessage());
        } finally {
            System.clearProperty("javax.net.debug");
        }
    }



    public static String doPostByHttpClient(String url, String data, String token) throws ConnectException {
        try {
            DefaultHttpClient httpClient = null;
            if (url.toLowerCase().startsWith("https://")) {
                System.out.println("use ssl");
                httpClient = new SSLClient();
            } else {
                System.out.println("use nonssl");
                httpClient = new DefaultHttpClient();
            }

            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json");
            httpPost.addHeader("api", "true");
            httpPost.addHeader("accessToken", token);

            StringEntity se = new StringEntity(data, "UTF-8");
            se.setContentType("text/json");
            se.setContentEncoding(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
            httpPost.setEntity(se);
            HttpResponse response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new ConnectException("连接银企服务器发生错误！");
            }
            String body = EntityUtils.toString(response.getEntity());
            System.out.println(body);
            return body;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(" ===== doPostByHttpClient() ERROR ===== ");
            throw new ConnectException(e.getMessage());
        } finally {
            System.clearProperty("javax.net.debug");
        }
    }

    public static String doGetByHttpClient(String url, String accessToken) throws ConnectException {
        System.out.println("url =" + url);

        try {
            // System.setProperty("javax.net.debug", "ssl");
            DefaultHttpClient httpClient = null;
            if (url.toLowerCase().startsWith("https://")) {
                System.out.println("use ssl");
                httpClient = new SSLClient();
            } else {
                System.out.println("use nonssl");
                httpClient = new DefaultHttpClient();
            }

            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpGet.addHeader("accessToken", accessToken);

            HttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new ConnectException("连接银企服务器发生错误！");
            }

            String body = EntityUtils.toString(response.getEntity());
            System.out.println(body);
            return body;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(" ===== doPostByHttpClient() ERROR ===== ");
            throw new ConnectException(e.getMessage());
        } finally {
            System.clearProperty("javax.net.debug");
        }
    }

    public static String postMan() throws IOException {
        OkHttpClient client = new OkHttpClient();

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\n    \"billno\": \"postman007\",\n    \"source\": 1,\n    \"city\": \"123\",\n    \"mobile\": \"18152646422\",\n    \"repairlocation\": \"上海市浦东新区\",\n    \"username\": \"陈先一\",\n    \"userid\": 1,\n    \"ownertype\": 1\n}");
        Request request = new Request.Builder()
                .url("http://172.29.5.177:8080/ierp/kapi/app/shkd_clueorbusi/clueSave")
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("accessToken", "H9XBAwRmCy6eVTyx0C9PgYaeAWht9bWxQbHn7ffBEhV2A3Bkjyf7M9UVITxwLIk3m9I3ZTrqNJiiOLIGqXMI4BzujyeinVE8xiNLbCzti2jAn3OHGhbh14ze167wDkWO")
                .addHeader("User-Agent", "PostmanRuntime/7.20.1")
                .addHeader("Accept", "*/*")
                .addHeader("Cache-Control", "no-cache")
                .addHeader("Postman-Token", "0b6709cd-7cae-44f2-bd02-4fb8e4728e4b,b9033ea9-0d59-45fd-9aee-4d1ec3289d46")
                .addHeader("Host", "172.29.5.177:8080")
                .addHeader("Accept-Encoding", "gzip, deflate")
                .addHeader("Content-Length", "208")
                .addHeader("Cookie", "KERPSESSIONIDcosmic-simple=H9XBAwRmCy6eVTyx0C9PgYaeAWht9bWxQbHn7ffBEhV2A3Bkjyf7M9UVITxwLIk3m9I3ZTrqNJiiOLIGqXMI4BzujyeinVE8xiNLbCzti2jAn3OHGhbh14ze167wDkWO; KERPSESSIONID=H9XBAwRmCy6eVTyx0C9PgYaeAWht9bWxQbHn7ffBEhV2A3Bkjyf7M9UVITxwLIk3m9I3ZTrqNJiiOLIGqXMI4BzujyeinVE8xiNLbCzti2jAn3OHGhbh14ze167wDkWO")
                .addHeader("Connection", "keep-alive")
                .addHeader("cache-control", "no-cache")
                .build();

        Response response = client.newCall(request).execute();
        return response.body().toString();
    }


}